<?php


namespace EchoPHP\Foundation\Support;


use EchoPHP\File\UploadedFile;

class FileBag extends ParameterBag {

    private static $fileKeys = ['error', 'name', 'size', 'tmp_name', 'type'];

    public function __construct(array $parameters = []) {
        $this->replace($parameters);
    }

    public function replace(array $files = []) {
        $this->parameters = [];
        $this->add($files);
    }

    public function add(array $files = []) {
        foreach ($files as $key => $file) {
            $this->set($key, $file);
        }
    }

    public function set($key, $value) {
        $value = $this->convertFileInformation($value);
        if (is_array($value)) {
            foreach ($value as $fileInstance) {
                if (!$fileInstance instanceof UploadedFile && !is_null($fileInstance)) {
                    throw new \Exception('a Uploaded File convert into UploadedFile Instance Failed');
                }
            }
        } else {
            if (!$value instanceof UploadedFile && !is_null($value)) {
                throw new \Exception('a Uploaded File convert into UploadedFile Instance Failed');
            }
        }

        parent::set($key, $value);
    }

    protected function convertFileInformation($file) {
        if ($file instanceof UploadedFile) {
            return $file;
        }
        $file = $this->fixPhpFilesArray($file);
        if (!is_array($file)) {
            return $file;
        }
        if (isset($file['name'])) {
            if (UPLOAD_ERR_NO_FILE == $file['error']) {
                $file = null;
            } else {
                $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['error']);
            }
        } else {
            $file = array_map([$this, 'convertFileInformation'], $file);
        }
        return $file;
    }

    /**
     * 修正同名文件上传的数组格式和单个文件数据格式不一致问题，全部整理成一致的文件格式方便处理
     * @param $data
     * @return array
     */
    protected function fixPhpFilesArray($data) {
        if (!is_array($data)) {
            return $data;
        }

        $keys = array_keys($data);
        sort($keys);

        if (self::$fileKeys != $keys || !isset($data['name']) || !is_array($data['name'])) {
            return $data;
        }

        $files = [];

        foreach ($data['name'] as $key => $name) {
            $files[$key] = $this->fixPhpFilesArray([
                'error' => $data['error'][$key],
                'name' => $name,
                'type' => $data['type'][$key],
                'tmp_name' => $data['tmp_name'][$key],
                'size' => $data['size'][$key],
            ]);
        }

        return $files;
    }

}